package com.wuliang.generate.common.core.basic;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.google.gson.annotations.Expose;
import com.wuliang.generate.common.core.utils.ClassUtils;
import lombok.Data;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.springframework.format.annotation.DateTimeFormat;

import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.sql.Timestamp;

/**
 * 实体类对象公共字段提取 转换成JSON格式时 忽略创建时间字段以及修改时间字段
 *
 * @author 邬魉
 */
@Data
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties
public class BasicEntity implements Serializable {

    /**
     * 各表主键ID
     */
    @Id
    @Expose
    @Column(name = "id", columnDefinition = " int(10) unsigned comment '主键ID'")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected Integer id;

    /**
     * 数据创建时间， 对时间格式进行统一格式化
     */
    @Expose
    @CreatedDate
    @DateTimeFormat(pattern = "YYYY-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyy-MM-dd HH:mm:ss")
    @Column(name = "create_time", columnDefinition = " datetime comment '数据创建时间'")
    Timestamp createTime;

    /**
     * 数据最后一次修改时间
     */
    @Expose
    @LastModifiedDate
    @Column(name = "modify_time", columnDefinition = " datetime comment '数据最后一次修改时间'")
    Timestamp modifyTime;

    /**
     * 数据类型(0: 正常; 1: 删除; 2: 锁定; 3: 过期;)
     */
    @Expose
    @Column(name = "data_status", columnDefinition = "int(1) default 0 comment '数据状态(0: 正常; 1: 删除; 2: 锁定; 3: 过期;)'")
    Integer dataStatus = 0;

    @Transient
    public <T extends BasicEntity> T marge(T entity) {
        if (entity == null) {
            return null;
        }
        if (entity.getId() != null && !entity.getId().equals(this.id)) {
            return entity;
        }
        Field[] entityFields = entity.getClass().getFields();
        for (Field entityField : entityFields) {
            Object targetFieldValue = ClassUtils.invokeGetterMethod(entity, entityField.getName());
            Object sourceFieldValue = ClassUtils.invokeGetterMethod(this, entityField.getName());
            if (targetFieldValue != null && !targetFieldValue.equals(sourceFieldValue)) {
                ClassUtils.invokeGetterMethod(this, entityField.getName());
            }
        }
        return (T) this;
    }
}
